<?php
class CV_Array{
	/**
	 * This class ist a static array helper only
	 */
	private function __construct(){}
	public static function column( $array, $field ){
		$column = array();
		foreach( $array as $key => $row ){
			if( isset($row[$field]) ){
				$column[$key] = $row[$field];
			} else {
				$column[$key] = NULL;
			}
		}
		return $column;
	}
	/**
	 * @return CV_Collection
	 */
	public static function group_by( $array, $fields ){
		$return = array();
		if( is_array($fields) ){
			$field = array_shift( $fields );
		} else {
			$field = $fields;
			$fields = array();
		}
	
		foreach( $array as $key => $value ){
			if( !isset($return[$value[$field]]) ){
				$return[$value[$field]] = array();
			}
			$return[$value[$field]][$key] = $value;
		}
		

		if( !empty($fields) ){
			foreach( $return as $key => $value ){
				$return[$key] = CV_Array::group_by( $value, $fields );
			}
		}
		
		return $return;
	}
	public static function reindex( $array, $index_key ){
		if( is_array($index_key) ){
			if( count($index_key) === 1 ){
				return self::reindex( $array, array_pop($index_key) );
			} else {
				$return = CV_Array::group_by( $array, array_shift($index_key) );
				foreach( $return as $key => $value ){
					$return[$key] = CV_Array::reindex( $value, $index_key );
				}
				return $return;
			}
		} else {
			if(is_array($array)) {
				if(count($array)) {
					$new_array = array();
					foreach( array_keys($array) as $key ) {
						if( !isset($array[$key]) ) {
							throw new Exception('$array is not a 2D-array');
						}
						if( !empty($array[$key][$index_key]) ){
							$new_array[ $array[$key][$index_key] ] = $array[$key];
						} else {
							$new_array[] = $array[$key];
						}
					}
					return $new_array;
				} else {
					return $array;
				}
			} else {
				throw new Exception('$array is not a 2D-array');
			}
		}
	}
	public static function dict( $array, $default = NULL ){
		$return = array();
		foreach( $array as $key => $value ){
			if( is_numeric($key) ){
				$return[$value] = $default;
			} else {
				$return[$key] = $value;
			}
		}
		return $return;
	}
	public static function flatten( $array ){
		$return = array();
		foreach( $array as $key => $item ){
			if( is_array($item) ){
				$return = array_merge( $return, $item );
			} else {
				$return[$key] = $item;
			}
		}
		return $return;
	}
	/**
	 * @internal
	 */
	public static $_columnsort_order;
	public static function columnsort(){
		$args = func_get_args();
		$array = array_shift( $args );
		self::$_columnsort_order = $args;
		uasort( $array, array(__CLASS__, '_columnsort_cmp') );
		return $array;
	}
	/**
	 * @internal
	 */
	public static function _columnsort_cmp( $a, $b, $columns = NULL ){
		if( $columns === NULL ){ // FIXME: move $columns preparation out of this function
			$raw_columns = self::$_columnsort_order;
			$columns = array();
			while( $name = array_shift($raw_columns) ){
				$column = array( 'name' => $name );
				$column['order'] = SORT_ASC;
				while( isset($raw_columns[0]) && is_int($raw_columns[0]) ){
					if( in_array($raw_columns[0], array(SORT_ASC, SORT_DESC)) ){
						$column['order'] = array_shift($raw_columns);
					}elseif( in_array($raw_columns[0], array(SORT_NUMERIC,SORT_STRING,SORT_LOCALE_STRING,SORT_REGULAR)) ){
						$column['type'] = array_shift($raw_columns);
					}else{
						trigger_error( "Invalid sort parameter '".$raw_columns[0]."'", E_USER_WARNING );
						return 0;
					}
				}
				$columns[] = $column;
			}
			return self::_columnsort_cmp( $a, $b, $columns );
		}
		if( empty($columns) ){
			return 0;
		}
		$column = array_shift( $columns );
		if( !isset($column['type']) ){
			if( is_numeric($a[$column['name']]) && is_numeric($b[$column['name']]) ){
				$type = SORT_NUMERIC;
			} else {
				$type = SORT_STRING;
			}
		} else {
			$type = $column['type'];
		}
		
		$order = $column['order'] === SORT_DESC ? -1 : 1;
		
		if( $type === SORT_REGULAR ){
			if    ( $a[$column['name']] < $b[$column['name']] ) $result = -1 * $order;
			elseif( $a[$column['name']] > $b[$column['name']] ) $result =  1 * $order;
			else $result = 0;
		}elseif( $type === SORT_NUMERIC ){
			if    ( (float)$a[$column['name']] < (float)$b[$column['name']] ) $result = -1 * $order;
			elseif( (float)$a[$column['name']] > (float)$b[$column['name']] ) $result =  1 * $order;
			else $result = 0;
		}else{
			$result = $order * strcoll( $a[$column['name']], $b[$column['name']] );
		}
		
		if( 0 === $result ){
			return self::_columnsort_cmp( $a, $b, $columns );
		}
		return $result;
	}
	function object_wrap( $array, $class ){
		$return = array();
		foreach( $array as $key => $item ){
			$return[$key] = new $class( $item );
		}
		return $return;
	}
}